#ifndef _SERIAL_H_
#define _SERIAL_H_

/********************************************//**
 * @class Serial
 *
 * @brief class to control the serial port communication.
 * @author Nathan vdv
 *
 ***********************************************/

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string>

#include "log.h"

//Defines
#define PARITY_8N1 1
#define PARITY_7E1 2
#define BUFFERSIZE	255

//Default serialport configuration
#define DEFAULTPORT "/dev/ttyS0"
#define DEFAULTSPEED 19200
#define DEFAULTDATABITS 8
#define DEFAULTBUFFERSIZE 1000
#define DEFAULTPARITY PARITY_8N1
#define DEFAULTBUFFERINDEX 0
#define DEFAULTBLOCKING 0

class Serial
{
public:

    /**
     * Constructor.
     * Initializes class variables.
     */
    Serial();

    /**
     * Constructor.
     * Initializes class variables.
     */
    Serial(string device, double baudrate);

    /**
     * Constructor.
     * Initializes class variables.
     */
    Serial(string device, double baudrate, int databits, int buffersize, int par, int bufferindex, int blocking);

    /**
     * Deconstructor.
     * Called when class instance is destroyed.
     */
    ~Serial();

    /**
     * Serial port initialization.
     * Opens a port and returns the file descriptor
     * @return int - file descriptor (value of -1 means init failed)
     */
    int initPort();

    /**
     * Read the buffer.
     * Polls the serial port for data and returns it to the host program
     * @param data - string to hold the new data
     * @return int - number of bytes collected
     */
    int getData(char* data);

    /**
     * Writes to the buffer.
     * @param data - string containing data to send
     * @return int - number of bytes sent
     */
    //int sendData(char* data);
    int sendData(unsigned char* data, int len) ;
    /**
     * Reads a byte from the buffer.
     * @return char - ASCII value of byte read, -1 if no byte read.
     */
    char getChar();

    /**
     * Sends a byte to the buffer.
     * @param data - The char to send to serial port.
     * @param return - Number of bytes sent.
     */
    int sendChar(char data);

    /**
     * Flush port.
     * Clears all data that is currently pending in either the transmit or receive buffers.
     */
    void flushPort();

    /**
     * Close port.
     * Serial port communication closed and port freed.
     */
    void closePort();

private:
    Log * logger;
    int fd;             /**< File descriptor for open port */
    string dev;         /**< Device string for serial port */
    int baud;           /**< Baud rate for serial port */
    int dataBits;       /**< Number of data bits for serial port */
    int bufferSize;     /**< Sets the size of the input buffer */
    int parity;         /**< Style of communication (8N1 or 7E1) */
    char temp[256];     /**< Temporary storage for getChar() function */
    char buffer[256];   /**< Buffer to hold extra bytes received */
    int bufferIndex;    /**< Location for next byte in buffer */
    int blocking;       /**< Flag for opening port in blocking mode */

    void init(string device, double baudrate, int databits, int buffersize, int par, int bufferindex, int blocking);

    void setDevice(string device);
    void setBaudRate(int baudrate);
    void setDataBits(int bits);
    void setBufferSize(int size);
    void setBufferIndex(int index);
    void setParity(int par);
    void setBlockingMode(int blockingmode);
};

#endif //_SERIAL_H
